// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraPlatformEmulationSettings.h"
#include "CommonUIVisibilitySubsystem.h"
#include "Engine/PlatformSettingsManager.h"
#include "Misc/App.h"
#include "Widgets/Notifications/SNotificationList.h"
#include "Framework/Notifications/NotificationManager.h"
#include "DeviceProfiles/DeviceProfileManager.h"
#include "DeviceProfiles/DeviceProfile.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraPlatformEmulationSettings)

// 定义本地化文本命名空间
#define LOCTEXT_NAMESPACE "LyraCheats"

/**
 * 构造函数
 */
ULyraPlatformEmulationSettings::ULyraPlatformEmulationSettings()
{
}

/**
 * 获取设置分类名称
 * @return 分类名称，返回项目名称
 */
FName ULyraPlatformEmulationSettings::GetCategoryName() const
{
	return FApp::GetProjectName();
}

/**
 * 获取模拟的基础设备配置文件名称
 * @return 设备配置文件名称
 */
FName ULyraPlatformEmulationSettings::GetPretendBaseDeviceProfile() const
{
	return PretendBaseDeviceProfile;
}

/**
 * 获取模拟的平台名称
 * @return 平台名称
 */
FName ULyraPlatformEmulationSettings::GetPretendPlatformName() const
{
	return PretendPlatform;
}

#if WITH_EDITOR
/**
 * 属性更改后处理函数
 * @param PropertyChangedEvent 属性更改事件
 */
void ULyraPlatformEmulationSettings::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	Super::PostEditChangeProperty(PropertyChangedEvent);

	// 应用设置
	ApplySettings();
}

/**
 * 配置重新加载后处理函数
 * @param PropertyThatWasLoaded 被加载的属性
 */
void ULyraPlatformEmulationSettings::PostReloadConfig(FProperty* PropertyThatWasLoaded)
{
	Super::PostReloadConfig(PropertyThatWasLoaded);

	// 应用设置
	ApplySettings();
}

/**
 * 属性初始化后处理函数
 */
void ULyraPlatformEmulationSettings::PostInitProperties()
{
	Super::PostInitProperties();

	// 应用设置
	ApplySettings();
}

/**
 * 当在编辑器中启动游戏时调用，显示平台特性覆盖激活的通知
 */
void ULyraPlatformEmulationSettings::OnPlayInEditorStarted() const
{
	// 如果设置了要启用的额外平台特性，显示通知提醒用户
	if (!AdditionalPlatformTraitsToEnable.IsEmpty())
	{
		// 创建通知信息
		FNotificationInfo Info(FText::Format(
			LOCTEXT("PlatformTraitEnableActive", "平台特性覆盖\n正在启用 {0}"),
			FText::AsCultureInvariant(AdditionalPlatformTraitsToEnable.ToStringSimple())
		));
		// 设置通知过期时间
		Info.ExpireDuration = 3.0f;
		// 添加通知
		FSlateNotificationManager::Get().AddNotification(Info);
	}

	// 如果设置了要抑制的额外平台特性，显示通知提醒用户
	if (!AdditionalPlatformTraitsToSuppress.IsEmpty())
	{
		// 创建通知信息
		FNotificationInfo Info(FText::Format(
			LOCTEXT("PlatformTraitSuppressionActive", "平台特性覆盖\n正在抑制 {0}"),
			FText::AsCultureInvariant(AdditionalPlatformTraitsToSuppress.ToStringSimple())
		));
		// 设置通知过期时间
		Info.ExpireDuration = 3.0f;
		// 添加通知
		FSlateNotificationManager::Get().AddNotification(Info);
	}

	// 如果设置了平台覆盖，显示通知提醒用户
	if (PretendPlatform != NAME_None)
	{
		// 创建通知信息
		FNotificationInfo Info(FText::Format(
			LOCTEXT("PlatformOverrideActive", "平台覆盖激活\n假装是 {0}"),
			FText::FromName(PretendPlatform)
		));
		// 设置通知过期时间
		Info.ExpireDuration = 3.0f;
		// 添加通知
		FSlateNotificationManager::Get().AddNotification(Info);
	}
}

/**
 * 应用设置，包括更新调试可见性条件和更改模拟平台
 */
void ULyraPlatformEmulationSettings::ApplySettings()
{
	// 设置调试可见性条件
	UCommonUIVisibilitySubsystem::SetDebugVisibilityConditions(AdditionalPlatformTraitsToEnable, AdditionalPlatformTraitsToSuppress);

	// 如果在编辑器中且模拟平台已更改，则更改活动的模拟平台
	if (GIsEditor && PretendPlatform != LastAppliedPretendPlatform)
	{
		ChangeActivePretendPlatform(PretendPlatform);
	}

	// 选择一个合理的基础设备配置文件
	PickReasonableBaseDeviceProfile();
}

/**
 * 更改活动的模拟平台
 * @param NewPlatformName 新的平台名称
 */
void ULyraPlatformEmulationSettings::ChangeActivePretendPlatform(FName NewPlatformName)
{
	// 更新最后应用的平台和当前平台
	LastAppliedPretendPlatform = NewPlatformName;
	PretendPlatform = NewPlatformName;

	// 设置编辑器模拟平台
	UPlatformSettingsManager::SetEditorSimulatedPlatform(PretendPlatform);
}

#endif

/**
 * 获取已知平台ID列表
 * @return 平台名称数组
 */
TArray<FName> ULyraPlatformEmulationSettings::GetKnownPlatformIds() const
{
	TArray<FName> Results;

#if WITH_EDITOR
	// 添加"无"选项
	Results.Add(NAME_None);
	// 添加已知和启用的平台INI名称
	Results.Append(UPlatformSettingsManager::GetKnownAndEnablePlatformIniNames());
#endif

	return Results;
}

/**
 * 获取已知设备配置文件列表
 * @return 设备配置文件名称数组
 */
TArray<FName> ULyraPlatformEmulationSettings::GetKnownDeviceProfiles() const
{
	TArray<FName> Results;
	
#if WITH_EDITOR
	// 获取设备配置文件管理器
	const UDeviceProfileManager& Manager = UDeviceProfileManager::Get();
	// 预留空间
	Results.Reserve(Manager.Profiles.Num() + 1);

	// 如果没有模拟平台，添加"无"选项
	if (PretendPlatform == NAME_None)
	{
		Results.Add(NAME_None);
	}

	// 遍历所有设备配置文件
	for (const TObjectPtr<UDeviceProfile>& Profile : Manager.Profiles)
	{
		bool bIncludeEntry = true;
		// 如果设置了模拟平台，只包含匹配该平台的配置文件
		if (PretendPlatform != NAME_None)
		{
			if (Profile->DeviceType != PretendPlatform.ToString())
			{
				bIncludeEntry = false;
			}
		}

		// 如果包含此条目，添加到结果中
		if (bIncludeEntry)
		{
			Results.Add(Profile->GetFName());
		}
	}
#endif

	return Results;
}

/**
 * 选择一个合理的基础设备配置文件
 */
void ULyraPlatformEmulationSettings::PickReasonableBaseDeviceProfile()
{
	// 首先检查我们的模拟设备配置文件是否已经兼容，如果是，则无需执行任何操作
	UDeviceProfileManager& Manager = UDeviceProfileManager::Get();
	// 查找配置文件
	if (UDeviceProfile* ProfilePtr = Manager.FindProfile(PretendBaseDeviceProfile.ToString(), /*bCreateOnFail=*/ false))
	{
		// 检查是否兼容
		const bool bIsCompatible = (PretendPlatform == NAME_None) || (ProfilePtr->DeviceType == PretendPlatform.ToString());
		if (!bIsCompatible)
		{
			// 如果不兼容，重置为基础设备配置文件
			PretendBaseDeviceProfile = NAME_None;
		}
	}

	// 如果模拟了平台但没有基础设备配置文件，选择一个合理的
	if ((PretendPlatform != NAME_None) && (PretendBaseDeviceProfile == NAME_None))
	{
		// 选择名称最短的匹配配置文件作为简单启发式方法
		FName ShortestMatchingProfileName;
		const FString PretendPlatformStr = PretendPlatform.ToString();
		// 遍历所有配置文件
		for (const TObjectPtr<UDeviceProfile>& Profile : Manager.Profiles)
		{
			// 检查设备类型是否匹配模拟平台
			if (Profile->DeviceType == PretendPlatformStr)
			{
				const FName TestName = Profile->GetFName();
				// 选择名称最短的配置文件
				if ((ShortestMatchingProfileName == NAME_None) || (TestName.GetStringLength() < ShortestMatchingProfileName.GetStringLength()))
				{
					ShortestMatchingProfileName = TestName;
				}
			}
		}
		// 设置选择的基础设备配置文件
		PretendBaseDeviceProfile = ShortestMatchingProfileName;
	}
}

// 取消本地化文本命名空间定义
#undef LOCTEXT_NAMESPACE